﻿using System;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;

namespace ServerUtils
{
    public class WCFService : IErrorHandler, IServiceBehavior
    {
        public event EventHandler<ErrorEventArgs> Error;

        public event EventHandler<FaultEventArgs> Fault;

        #region IErrorHandler

        public bool HandleError(Exception error)
        {
            var e = new ErrorEventArgs(error);
            this.OnError(e);
            return e.KeepSessionAndInstance;
        }

        public void ProvideFault(Exception error, System.ServiceModel.Channels.MessageVersion version, ref System.ServiceModel.Channels.Message fault)
        {
            var e = new FaultEventArgs(error);
            this.OnFault(e);
            if (e.CustomFaultException != null)
            {
                MessageFault messageFault = e.CustomFaultException.CreateMessageFault();
                fault = Message.CreateMessage(version, messageFault, e.CustomFaultException.Action);
            }
        }

        #endregion

        #region IServiceBehavior

        public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
        {
            foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
            {
                dispatcher.ErrorHandlers.Add(this);
            }
        }

        public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
        {
        }

        #endregion

        protected virtual void OnError(ErrorEventArgs e)
        {
            EventHandler<ErrorEventArgs> handler = this.Error;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        protected virtual void OnFault(FaultEventArgs e)
        {
            EventHandler<FaultEventArgs> handler = this.Fault;
            if (handler != null)
            {
                handler(this, e);
            }
        }
    }
}
